/*
 *  Openmysee
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#ifndef __BALLOONHELP_H_
#define __BALLOONHELP_H_

#include <string>
#include <tchar.H>
#include <ATLSTR.h>
#include <ATLTYPES.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlwin.h>
#include <atlcoll.h>

class CBalloonHelp : public CWindowImpl<CBalloonHelp>
{
public:
	CBalloonHelp();
	virtual ~CBalloonHelp();

	static ATL::CWndClassInfo& GetWndClassInfo() 
	{ 
		static ATL::CWndClassInfo wc = 
		{ 
//			{ sizeof(WNDCLASSEX), CS_DBLCLKS | CS_SAVEBITS | CS_DROPSHADOW, StartWindowProc, 
			{ sizeof(WNDCLASSEX), CS_DBLCLKS | CS_SAVEBITS, StartWindowProc, 
			0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, _T("BalloonHelpClass"), NULL}, 
			NULL, NULL, IDC_ARROW, TRUE, 0, _T("") 
		}; 
		return wc; 
	}

	// options
	static const unsigned int unHIDE_AFTER_CREATED;
	static const unsigned int unCLOSE_ON_LBUTTON_UP;   // closes window on WM_LBUTTON_UP
	static const unsigned int unCLOSE_ON_RBUTTON_UP;   // closes window on WM_RBUTTON_UP
	static const unsigned int unCLOSE_ON_MOUSE_MOVE;   // closes window when user moves mouse past threshhold
	static const unsigned int unCLOSE_ON_KEYPRESS;     // closes window on the next keypress message sent to this thread.    (!!! probably not thread safe !!!)
	static const unsigned int unDELETE_THIS_ON_CLOSE;  // deletes object when window is closed.  Used by LaunchBalloon(), use with care
	static const unsigned int unSHOW_CLOSE_BUTTON;     // shows close button in upper right
	static const unsigned int unSHOW_INNER_SHADOW;     // draw inner shadow in balloon
	static const unsigned int unSHOW_TOPMOST;          // place balloon above all other windows
	static const unsigned int unDISABLE_FADEIN;        // disable the fade-in effect (overrides system and user settings)
	static const unsigned int unDISABLE_FADEOUT;       // disable the fade-out effect (overrides system and user settings)
	static const unsigned int unDISABLE_FADE;          // disable the fade-in/fade-out effects (overrides system and user settings)

	BOOL Create(const CString& strTitle,         // title of balloon
				const CString& strContent,       // content of balloon
				const CPoint& ptAnchor,          // anchor (tail position) of balloon
				unsigned int unOptions,          // options (see above)
				HWND pParentWnd = NULL,         // parent window (NULL == MFC main window)
				const CString strURL = "",       // URL to open (ShellExecute()) when clicked
				unsigned int unTimeout = 0,      // delay before closing automatically (milliseconds)
				HICON hIcon = NULL);             // icon to display

	// Show a help balloon on screen.
	static void LaunchBalloon(const CString& strTitle, const CString& strContent, 
				const CPoint& ptAnchor, 
				LPCTSTR szIcon = IDI_EXCLAMATION,
				unsigned int unOptions = unSHOW_CLOSE_BUTTON,
				HWND pParentWnd = NULL, 
				const CString strURL = "",
				unsigned int unTimeout = 10000);

	// Sets the font used for drawing the balloon title.  Deleted by balloon, do not use CFont* after passing to this function.
	void SetTitleFont(HFONT);
	// Sets the font used for drawing the balloon content.  Deleted by balloon, do not use CFont* after passing to this function.
	void SetContentFont(HFONT);
	// Sets the icon displayed in the top left of the balloon (pass NULL to hide icon)
	void SetIcon(HICON hIcon);
	// Sets the icon displayed in the top left of the balloon (pass NULL hBitmap to hide icon)
	void SetIcon(HBITMAP hBitmap, COLORREF crMask);
	// Sets the icon displayed in the top left of the balloon
	void SetIcon(HBITMAP hBitmap, HBITMAP hMask);
	// Set icon displayed in the top left of the balloon to image # nIconIndex from pImageList
	void SetIcon(HIMAGELIST pImageList, int nIconIndex);
	// Sets the URL to be opened when balloon is clicked.  Pass "" to disable.
	void SetURL(const CString& strURL);
	// Sets the number of milliseconds the balloon can remain open.  Set to 0 to disable timeout.
	void SetTimeout(unsigned int unTimeout);
	// Sets the distance the mouse must move before the balloon closes when the unCLOSE_ON_MOUSE_MOVE option is set.
	void SetMouseMoveTolerance(int nTolerance);
	// Sets the CPoint to which the balloon is "anchored"
	void SetAnchorPoint(CPoint ptAnchor);
	// Sets the title of the balloon
	void SetTitle(const CString& strTitle);
	// Sets the content of the balloon (plain text only)
	void SetContent(const CString& strContent);
	// Sets the forground (text and border) color of the balloon
	void SetForegroundColor(COLORREF crForeground);
	// Sets the background color of the balloon
	void SetBackgroundColor(COLORREF crBackground);
	// Size and position the balloon window on the screen.
	void PositionWindow(bool forceRedraw=false);
	// Displays the balloon on the screen, performing fade-in if enabled.
	void ShowBalloon(void);
	// Removes the balloon from the screen, performing the fade-out if enabled
	void HideBalloon(void);
	// Removes the balloon from the screen immediately
	void HideBalloonImmediately(void);

protected:
	// layout constants
	static const int nTIP_TAIL;
	static const int nTIP_MARGIN;
	// mouse move tolerance
	static const int nMOUSE_MOVE_TRIGGER;

	enum BALLOON_QUADRANT { BQ_TOPRIGHT, BQ_TOPLEFT, BQ_BOTTOMRIGHT, BQ_BOTTOMLEFT };
	BALLOON_QUADRANT GetBalloonQuadrant();

	// Calculate the dimensions and draw the balloon header
	virtual CSize DrawHeader(HDC pDC, bool bDraw = TRUE);
	// Calculate the dimensions and draw the balloon contents
	virtual CSize DrawContent(HDC pDC, int nTop, bool bDraw = TRUE);
	// Calculate the dimensions required to draw the balloon header
	CSize CalcHeaderSize(HDC pDC) { return DrawHeader(pDC, FALSE); }
	// Calculate the dimensions required to draw the balloon content
	CSize CalcContentSize(HDC pDC) { return DrawContent(pDC, 0, FALSE); }
	// Calculate the total size needed by the balloon window
	CSize CalcWindowSize();
	// Calculate the total size needed by the client area of the balloon window
	CSize CalcClientSize();

BEGIN_MSG_MAP(CBalloonHelp)
	MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
	MESSAGE_HANDLER(WM_PAINT, OnPaint)
	MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
	MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
	MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
	MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
	MESSAGE_HANDLER(WM_TIMER, OnTimer)
	MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
	MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
	MESSAGE_HANDLER(WM_RBUTTONUP, OnRButtonUp)
	MESSAGE_HANDLER(WM_CLOSE, OnClose)
END_MSG_MAP()

	LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

private:
	// keyboard hook callback
	static LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam);
	// handle to the hook, if set
	static HHOOK            s_hKeyboardHook;
	// windows to close when user hits a key
	static CAtlArray<HWND>  s_apKeyboardCloseWnds;
	// synchronization
	static CComCriticalSection s_KeyboardHookSection;

	// Sets up the keyboard hook; adds this to list to close
	void SetKeyboardHook();
	// Removes this from the list of windows to close; removes hook if not in use.
	void RemoveKeyboardHook();

	// Wrapper for possibly-existing API call
	BOOL SetLayeredWindowAttributes(COLORREF crKey, int nAlpha, DWORD dwFlags);
	// layered window API, if available
	typedef BOOL (WINAPI* FN_SET_LAYERED_WINDOW_ATTRIBUTES)(HWND,COLORREF,BYTE,DWORD);
	FN_SET_LAYERED_WINDOW_ATTRIBUTES m_fnSetLayeredWindowAttributes;

	unsigned int   m_unOptions;
	unsigned int   m_unTimeout;      // max time to show, in milliseconds
	CString        m_strTitle;       // text to shwo in title area
	CString        m_strContent;     // text to show in content area
	CString        m_strURL;         // url to open, if clicked.
	CPoint          m_ptAnchor;       // "anchor" (CPoint of tail)
	HIMAGELIST     m_ilIcon;         // icon

	HFONT          m_pTitleFont;     // font to use for title
	HFONT          m_pContentFont;   // font to use for content
	   
	COLORREF       m_crBackground;   // Background color for balloon   
	COLORREF       m_crForeground;   // Foreground color for balloon
	   
	HRGN           m_rgnComplete;    // Clipping / Drawing region
	int            m_nAlpha;         // current alpha, for fade in / fade out
	CPoint          m_ptMouseOrig;    // original mouse position; for hiding on mouse move
	UINT           m_uCloseState;    // current state of the close button
	int            m_nMouseMoveTolerance;  // distance mouse has to move before balloon will close.

protected:
	void OnFinalMessage(HWND);
};

#endif